package com.app.annotion;


import com.app.aspect.RedisLock;
import com.app.common.Result;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class RedisLockAspect {

    @Autowired
    private RedisLock redisLock;

    @Around("@annotation(redisLockAnnotation)")
    public Object around(ProceedingJoinPoint joinPoint, RedisLockAnnotation redisLockAnnotation) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs();
        String[] paramNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(method);
        ExpressionParser parser = new SpelExpressionParser();
        StandardEvaluationContext context = new StandardEvaluationContext();
        for (int len = 0; len < paramNames.length; len++) {
            context.setVariable(paramNames[len], args[len]);
        }
        String key = redisLockAnnotation.prefix() + parser.parseExpression(redisLockAnnotation.key()).getValue(context, String.class);
        long timeout = redisLockAnnotation.timeout();

        boolean lock = redisLock.lock(key, "value", timeout);
        if (!lock) {
            // 在这里返回一个特定的结果类型，表示无法获取锁
            return Result.error(500,"网络开小差,请稍后重试");
        }
        try {
            return joinPoint.proceed();
        } finally {
            redisLock.unlock(key);
        }
    }





}
